package cn.fl.mcr.controller;

import cmm.mid.core.framework.page.DataResultVO;
import cmm.mid.core.framework.page.ListPageVO;
import cmm.web.core.framework.controller.BaseController;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.utils.BaseLogUtils;
import cn.cmm.base.framework.utils.CollectionUtils;
import cn.cmm.base.framework.utils.DecimalUtils;
import cn.fl.framework.base.context.CurrentThreadContext;
import cn.fl.mcr.export.McrBillCheckDetailExportBean;
import cn.fl.mcr.export.McrBillCheckExportBean;
import cn.fl.mcr.export.WKRemittanceRecordExportBean;
import cn.fl.mcr.export.YXRemittanceRecordExportBean;
import cn.fl.mcr.service.IMcrBillCheckService;
import cn.fl.mcr.vo.McrLoanChannelVO;
import cn.fl.system.constant.SysLogConstant;
import cn.lb.framework.poi.excel.ExcelExportUtil;
import cn.lb.framework.poi.excel.entity.ExportParams;
import cn.lb.framework.poi.excel.entity.enmus.ExcelType;
import cn.lb.framework.poi.excel.export.styler.ExcelExportStylerDefaultImpl;
import cn.lionbridgecapital.loan.model.base.Pager;
import cn.lionbridgecapital.loan.model.condition.McrBillCheckQC;
import cn.lionbridgecapital.loan.model.condition.McrLoanChannelQC;
import cn.lionbridgecapital.loan.model.constant.McrBillMConstant;
import cn.lionbridgecapital.loan.model.dto.McrLoanChannelDTO;
import cn.lionbridgecapital.loan.model.utils.Safes;
import cn.lionbridgecapital.loan.model.vo.McrBillCheckVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description: 资方放款文件对账
 *
 * @Author: shaozhou.li
 * @Date: 2020/4/17 20:46
 */
@Controller
@RequestMapping("/mcr/mcrBillCheck")
public class McrBillCheckController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(McrBillCheckController.class);

    @Resource
    private IMcrBillCheckService mcrBillCheckService;

    // 导出差异文件
    private static final String EXPORT_DIFF = "diffFile";
    // 导出资方文件
    private static final String EXPORT_WK = "loanFile";

    /**
     * 到列表页面
     */
    @RequestMapping(value = "/toListPage.do", method = { RequestMethod.GET})
    public ModelAndView toListPage(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("mcr/mcrBillCheck/mcrBillCheckList");
        BaseLogUtils.info(logger, "toListPage", "跳转到列表页面.", CurrentThreadContext.getCurrentUserName());
        return view;
    }

    /**
     * 初始化列表
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/initList.do", method = { RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Object initList(HttpServletRequest request, HttpServletResponse response) {

        String currentPage = request.getParameter("page");
        String pageSize = request.getParameter("pagesize");
        String fileDateStart = request.getParameter("fileDateStart");
        String fileDateEnd = request.getParameter("fileDateEnd");
        String loanChannel = request.getParameter("loanChannel");
        String checkType = request.getParameter("checkType");
        String checkTimeStart = request.getParameter("checkTimeStart");
        String checkTimeEnd = request.getParameter("checkTimeEnd");
        String diffStatus = request.getParameter("diffStatus");
        String fileStatus = request.getParameter("fileStatus");

        Pager page = new Pager();
        if (StringUtils.isNotEmpty(currentPage)) {
            page.setCurrentPage(Integer.parseInt(currentPage));
        }
        if (StringUtils.isNotEmpty(pageSize)) {
            page.setEveryPage(Integer.parseInt(pageSize));
        }
        McrBillCheckQC mcrBillCheckQC = new McrBillCheckQC();
        mcrBillCheckQC.setDiffStatus(diffStatus);
        mcrBillCheckQC.setFileStatus(fileStatus);
        if (StringUtils.isNotBlank(loanChannel)){
            mcrBillCheckQC.setLoanChannel(loanChannel);
        }
        if (StringUtils.isNotBlank(checkType)){
            mcrBillCheckQC.setCheckType(Long.parseLong(checkType));
        }
        ListPageVO<McrBillCheckVO> listPage = null;
        try{
            if (StringUtils.isNotBlank(fileDateStart)){
                mcrBillCheckQC.setFileDateStart(fileDateStart);
            }
            if (StringUtils.isNotBlank(fileDateEnd)){
                mcrBillCheckQC.setFileDateEnd(fileDateEnd);
            }
            if (StringUtils.isNotBlank(checkTimeStart)){
                mcrBillCheckQC.setCheckTimeStart(checkTimeStart);
            }
            if (StringUtils.isNotBlank(fileDateStart)){
                mcrBillCheckQC.setCheckTimeEnd(checkTimeEnd);
            }
            page.setCondition(mcrBillCheckQC);

            Pager pager = this.mcrBillCheckService.searchListPage(page);
            List<McrBillCheckVO> list = (List<McrBillCheckVO>) pager.getResultList();
            listPage = new ListPageVO<>(list, pager.getTotalCount());

        }catch (Exception ex){
            BaseLogUtils.error(logger,"initList","初始化参数异常.ex:"+ex.getMessage(),ex);
        }
        BaseLogUtils.info(logger, "initList", "查询数据完成. DATA:" + JSONObject.toJSONString(page), CurrentThreadContext.getCurrentUserName());
        return listPage;
    }

    /**
     * 对账导出
     */
    @RequestMapping(value = "/billCheckExport.do", method = {RequestMethod.GET, RequestMethod.POST})
    public void outExcel(HttpServletRequest request, HttpServletResponse response) {
        BaseLogUtils.info(logger,"billCheckExport","对账导出.操作人:"+CurrentThreadContext.getCurrentUserId());

        String checkId = request.getParameter("checkId");
        String outExcelType = request.getParameter("outExcelType");
        BaseLogUtils.info(logger, "billCheckExport", "对账导出.参数：checkId=" + checkId + "，outExcelType="+outExcelType);

        try {
            McrBillCheckVO billCheckVO = mcrBillCheckService.searchMcrBillCheck(Long.valueOf(checkId));
            if (Objects.isNull(billCheckVO)) {
                throw new BaseException("请求数据不存在!");
            }

            BaseLogUtils.info(logger, "billCheckExport", "查询文件数据："+ JSONObject.toJSONString(billCheckVO));

            DateTimeFormatter dtFormatter = DateTimeFormatter.ISO_DATE_TIME.ofPattern("yyyyMMddHHmmss");
            String fileDateTime = LocalDateTime.now().format(dtFormatter);
            String loanName = McrBillMConstant.LOAN_CHANNEL_DESC_MAP.get(billCheckVO.getLoanChannel());

            // 导出差异文件
            if (StringUtils.equals(outExcelType, EXPORT_DIFF)) {
                String fileName = loanName + "差异文件" + "_" + fileDateTime;

                List<McrBillCheckExportBean> list = mcrBillCheckService.exportDiffDetail(Long.valueOf(checkId));

                BaseLogUtils.info(logger, "billCheckExport", "导出差异文件："+ JSONObject.toJSONString(list));

                export(fileName, McrBillCheckExportBean.class, list, response);
                return;
            }
            String fileName = loanName + "放款文件" + "_" + fileDateTime;
            List<String> fileContents = mcrBillCheckService.readLoanFile(Long.valueOf(checkId));
            BaseLogUtils.info(logger, "billCheckExport", "资方原文件内容："+ JSONObject.toJSONString(fileContents));

            // 五矿原文件
            if (StringUtils.equals(billCheckVO.getLoanChannel(), McrBillMConstant.LOAN_CHANNEL_WKXT)) {
                List<WKRemittanceRecordExportBean> list = Safes.of(fileContents).stream()
                        .map(it -> analysisWkTxt(it))
                        .collect(Collectors.toList());

                BaseLogUtils.info(logger, "billCheckExport", "导出五矿原文件："+ JSONObject.toJSONString(list));

                export(fileName, WKRemittanceRecordExportBean.class, list, response);
                return;
            }

            // 云信原文件
            if (StringUtils.equals(billCheckVO.getLoanChannel(), McrBillMConstant.LOAN_CHANNEL_YNXT)) {
                List<YXRemittanceRecordExportBean> list = Safes.of(fileContents).stream()
                        .map(it -> JSONObject.parseObject(it, YXRemittanceRecordExportBean.class))
                        .collect(Collectors.toList());

                BaseLogUtils.info(logger, "billCheckExport", "导出云信原文件："+ JSONObject.toJSONString(list));

                export(fileName, YXRemittanceRecordExportBean.class, list, response);
                return;
            }

        } catch (BaseException e) {
            BaseLogUtils.error(logger, "billCheckExport", "对账导出.ERROR：" + e.getMessage(), CurrentThreadContext.getCurrentUserName());
        } catch (Exception e) {
            BaseLogUtils.error(logger, "billCheckExport", "对账导出,系统错误..ERROR:" + e.getMessage(), CurrentThreadContext.getCurrentUserName());
        }
    }

    /**
     * 五矿文件解析
     * @param txtLine
     * @return
     */
    private WKRemittanceRecordExportBean analysisWkTxt(String txtLine) {
        // 文件内容分隔符：|+|
        String[] content = txtLine.split("\\|\\+\\|");

        WKRemittanceRecordExportBean exportBean = new WKRemittanceRecordExportBean();

        // 批次号
        exportBean.setBatchNo(content[0]);
        // 合作机构号
        exportBean.setCooperateGroupNo(content[1]);
        // 贷款合同号
        exportBean.setContractNo(content[2]);
        // 客户名称
        exportBean.setCstNm(content[3]);
        // 放款日期
        exportBean.setLoanDate(content[4]);
        // 放款时间
        exportBean.setCurrency(content[5]);
        // 放款金额
        exportBean.setCrAmt(content[6]);
        // 放款状态
        exportBean.setTradeStatus(content[7]);
        // 放款时间
        exportBean.setCompleteTime(content[8]);
        // 放款银行
        exportBean.setBankName(content[9]);
        // 放款账户
        exportBean.setBankAccount(content[10]);
        // 放款渠道
        exportBean.setGateway(content[11]);
        // 交易结果描述
        if (StringUtils.equals(content[7], "04")) {
            exportBean.setRemark(content[12]);
        }

        return exportBean;
    }

    /**
     * 数据导出
     * @param fileName
     * @param classz
     * @param data
     * @param response
     */
    private void export(String fileName, Class classz, List data, HttpServletResponse response) {
        String excelTitle = fileName;
        String sheetName = fileName;
        ExportParams params = new ExportParams(excelTitle, sheetName, ExcelType.HSSF);
        //HSSF是POI工程对Excel 97(-2007)文件操作的纯Java实现;
        //XSSF是POI工程对Excel 2007 OOXML (.xlsx)文件操作的纯Java实现
        //SXSSF基于XSSF的低内存占用的API
        params.setColor(HSSFColor.BRIGHT_GREEN.index);//表头颜色
        params.setStyle(ExcelExportStylerDefaultImpl.class);//ExcelExportStylerBorderImpl 有边框样式 ExcelExportStylerColorImpl  有边框间隔行样式 ExcelExportStylerDefaultImpl	默认的样式
        Workbook workbook = ExcelExportUtil.exportExcel(params, classz, data);
        OutputStream ouputStream = null;
        try {
            fileName=new String(fileName.getBytes("UTF-8"),"ISO8859-1");
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");// 设定输出文件头
            response.setContentType("application/x-msdownload");// 定义输出类型
            ouputStream = response.getOutputStream();
            workbook.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (UnsupportedEncodingException e) {
            BaseLogUtils.error(logger, "-", "异常", e);
        } catch (IOException e) {
            BaseLogUtils.error(logger, "-", "异常", e);
        }finally {
            //关闭流
            if(ouputStream!=null){
                try {
                    ouputStream.close();
                } catch (IOException e) {
                    BaseLogUtils.error(logger, "-", "异常", e);
                }
            }
        }
    }


    @RequestMapping(value = "/toCheckDetail.do", method = { RequestMethod.GET, RequestMethod.POST })
    public ModelAndView toCheckDetail(HttpServletRequest request, HttpServletResponse response) {
        Long startTm = System.currentTimeMillis();
        BaseLogUtils.info(logger, "toCheckDetail", "加载对账详情页面.请求参数：" + this.getRequestParameter(request), CurrentThreadContext.getCurrentUserName());

        String id = request.getParameter("id");
        ModelAndView view = new ModelAndView("mcr/mcrBillCheck/mcrBillCheckDetail");
        //获取对账结果
        McrBillCheckVO mcrBillCheckVO = mcrBillCheckService.searchMcrBillCheck(Long.valueOf(id));
        view.addObject("id", id);
        view.addObject("mcrBillCheckVO", mcrBillCheckVO);
        view.addObject("resultList", JSON.toJSONString(Arrays.asList(mcrBillCheckVO)));
        Long endTm = System.currentTimeMillis();
        BaseLogUtils.info(logger, "toAddPage", "加载对账详情页面.耗时：" + (endTm-startTm), CurrentThreadContext.getCurrentUserName());
        return view;
    }

    /**
     * 对账导出
     */
    @RequestMapping(value = "/exportDetailFile.do", method = {RequestMethod.GET, RequestMethod.POST})
    public void exportDetailFile(HttpServletRequest request, HttpServletResponse response) {
        BaseLogUtils.info(logger,"exportDetailFile","对账详情导出.操作人:"+CurrentThreadContext.getCurrentUserId());

        String checkId = request.getParameter("checkId");
        BaseLogUtils.info(logger, "billCheckExport", "对账导出.参数：checkId=" + checkId);

        try {
            McrBillCheckVO billCheckVO = mcrBillCheckService.searchMcrBillCheck(Long.valueOf(checkId));
            if (Objects.isNull(billCheckVO)) {
                throw new BaseException("请求数据不存在!");
            }

            BaseLogUtils.info(logger, "billCheckExport", "查询文件数据：" + JSONObject.toJSONString(billCheckVO));

            DateTimeFormatter dtFormatter = DateTimeFormatter.ISO_DATE_TIME.ofPattern("yyyyMMddHHmmss");
            String fileDateTime = LocalDateTime.now().format(dtFormatter);
            String loanName = McrBillMConstant.LOAN_CHANNEL_DESC_MAP.get(billCheckVO.getLoanChannel());

            String fileName = loanName + "对账详情" + "_" + fileDateTime;
            List<McrBillCheckDetailExportBean> listBillAfterCheckDDTO = mcrBillCheckService.searchMcrBillCheckDetail(Long.valueOf(checkId));
            BaseLogUtils.info(logger, "billCheckExport", "导出对账明细文件：" + JSONObject.toJSONString(listBillAfterCheckDDTO));
            export(fileName, McrBillCheckDetailExportBean.class, listBillAfterCheckDDTO, response);
        } catch (BaseException e) {
            BaseLogUtils.error(logger, "billCheckExport", "对账导出.ERROR：" + e.getMessage(), CurrentThreadContext.getCurrentUserName());
        } catch (Exception e) {
            BaseLogUtils.error(logger, "billCheckExport", "对账导出,系统错误..ERROR:" + e.getMessage(), CurrentThreadContext.getCurrentUserName());
        }
    }


    /**
     * 修改
     */
    @RequestMapping(value = "/modify.do")
    @ResponseBody
    public Object modify(HttpServletRequest request, HttpServletResponse response, McrBillCheckVO entity) throws BaseException {
        String id = request.getParameter("id");
        DataResultVO result = new DataResultVO(BaseConstant.IS_YESNO_YES, SysLogConstant.LOG_CMM_UPDATE_SUCC);
        if(cn.cmm.base.framework.utils.StringUtils.isEmpty(id)){
            result.setSuccess(BaseConstant.IS_YESNO_NO);
            result.setInfo(SysLogConstant.LOG_CMM_DATA_PK_IS_EMPTY);
            BaseLogUtils.info(logger, "modify", "修改数据,主键不存在.[id="+id+"]", CurrentThreadContext.getCurrentUserName());
            return result;
        }
        try {
            entity.setId(Long.valueOf(id));
            boolean success = this.mcrBillCheckService.modify(entity);
            if(!success){
                result.setSuccess(BaseConstant.IS_YESNO_NO);
                result.setInfo(SysLogConstant.LOG_CMM_SYS_ERROR);
                BaseLogUtils.info(logger, "modify", "修改失败.[id="+id+"] DATA:" + JSONObject.toJSONString(entity), CurrentThreadContext.getCurrentUserName());
            }
            BaseLogUtils.info(logger, "modify", "修改成功.[id="+id+"] DATA:" + JSONObject.toJSONString(entity), CurrentThreadContext.getCurrentUserName());
        }catch (BaseException ex) {
            result.setSuccess(BaseConstant.IS_YESNO_NO);
            result.setInfo(ex.getMessage());
            BaseLogUtils.info(logger, "modify", "修改失败.[id="+id+"] DATA:" + JSONObject.toJSONString(entity) + ex.getMessage(), CurrentThreadContext.getCurrentUserName());
        }catch (Exception ex) {
            result.setSuccess(BaseConstant.IS_YESNO_NO);
            result.setInfo(SysLogConstant.LOG_CMM_SYS_ERROR);
            BaseLogUtils.error(logger, "modify", "修改失败.[id="+id+"] DATA:" + JSONObject.toJSONString(entity) + ex.getMessage(), CurrentThreadContext.getCurrentUserName());
        }
        return result;
    }

}
